package gwt.board.demo.client;

import gwt.gwtisometricboard.client.BoardDrawer;
import gwt.gwtisometricboard.client.model.Tile;

import com.google.gwt.canvas.client.Canvas;
import com.google.gwt.canvas.dom.client.Context2d;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.dom.client.Document;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;

import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.RadioButton;
import com.google.gwt.user.client.ui.RootPanel;

import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.CaptionPanel;

public class BoardDemo implements EntryPoint {

	private VerticalPanel mainPanel = new VerticalPanel();
	private HorizontalPanel aPanel = new HorizontalPanel();
	private Button drawBoardButton = new Button("Draw Board");
	private Button zoomInButton = new Button("Zoom In");
	private Button zoomOutButton = new Button("Zoom Out");
	private RadioButton displayPositionOption = new RadioButton("ActionGroup",
			"Display Position");
	private RadioButton moveUnitOption = new RadioButton("ActionGroup",
			"Move Unit");
	private Label msgsLabel = new Label();
	protected static final int WIDTH = 1020, HEIGHT = 600;
	Canvas canvas;
	private Context2d context;
	private BoardDrawer bd;

	private Tile tileWithUnit = null;
	private TestImageProvider imageProvider;
	private final VerticalPanel buttonsVerticalPanel = new VerticalPanel();
	private final CaptionPanel cptnpnlButtonPanel = new CaptionPanel("Actions");
	private final CaptionPanel cptnpnlBoardClickAction = new CaptionPanel(
			"Board Click Action:");
	private final VerticalPanel optionsVerticalPanel = new VerticalPanel();
	private final VerticalPanel optionsAndLabelVerticalPanel = new VerticalPanel();
	private final CaptionPanel cptnpnlActionResult = new CaptionPanel(
			"Action Result");

	/**
	 * Entry point method.
	 */
	public void onModuleLoad() {

		canvas = Canvas.createIfSupported();

		if (canvas == null) {
			RootPanel
					.get()
					.add(new Label(
							"Sorry, your browser doesn't support the HTML5 Canvas element"));
			return;
		}

		setupCanvasAndContext();

		// initializes the image provider
		imageProvider = new TestImageProvider(Document.get());

		// generates a map model
		TestTile[] testTiles = generateInitialMapModel();

		// adds some variety to the terrain
		testTiles[10].setBasicTileType("desert");
		testTiles[35].setBasicTileType("plains");
		testTiles[36].setBasicTileType("plains");
		testTiles[43].setBasicTileType("plains");
		testTiles[44].setBasicTileType("plains");

		// adds an unit to a tile in the map, so we can move it around
		testTiles[33].getThingList().add(new TestUnit());

		// remembers which tile contains the unit,to remove the unit from it
		// when
		// it moves to another tile.
		tileWithUnit = testTiles[33];

		// initializes the board drawer.
		bd = new BoardDrawer(testTiles, context, imageProvider, 8, 8, 64, 128,
				true, true, true);

		aPanel.add(cptnpnlButtonPanel);
		cptnpnlButtonPanel.setContentWidget(buttonsVerticalPanel);
		buttonsVerticalPanel.setSize("148px", "104px");
		buttonsVerticalPanel.add(drawBoardButton);
		drawBoardButton.setWidth("148px");

		// Listen for mouse events on the DrawBoard button.
		drawBoardButton.addClickHandler(new DrawBoardClickHandler());
		buttonsVerticalPanel.add(zoomInButton);
		zoomInButton.setWidth("148px");
		buttonsVerticalPanel.add(zoomOutButton);
		zoomOutButton.setWidth("148px");

		// Listen for mouse events on the Zoom Out button.
		zoomOutButton.addClickHandler(new ZoomOutButtonClickHandler());

		// Listen for mouse events on the Zoom In button.
		zoomInButton.addClickHandler(new ZoomInButonClickHandler());
		aPanel.add(optionsAndLabelVerticalPanel);
		optionsAndLabelVerticalPanel.add(cptnpnlBoardClickAction);
		cptnpnlBoardClickAction.setContentWidget(optionsVerticalPanel);
		optionsVerticalPanel.setSize("5cm", "46px");
		optionsVerticalPanel.add(displayPositionOption);

		// sets the default option.
		displayPositionOption.setValue(true);
		optionsVerticalPanel.add(moveUnitOption);
		optionsAndLabelVerticalPanel.add(cptnpnlActionResult);
		cptnpnlActionResult.setHeight("52px");
		cptnpnlActionResult.setContentWidget(msgsLabel);
		msgsLabel.setSize("5cm", "30px");

		// adds the panel and the canvas to the main panel.
		mainPanel.add(aPanel);
		mainPanel.add(canvas);

		// // Associate the Main panel with the HTML host page.
		RootPanel.get("boardDemo").add(mainPanel);
		mainPanel.setSize("392px", "128px");

		// draws the board.
		bd.drawBoard();

		//
		canvas.addClickHandler(new CanvasClickHandler());

	}

	private TestTile[] generateInitialMapModel() {
		TestTile[] testTiles = new TestTile[64];
		int n = 0;
		for (int i = 0; i < 8; i++) {
			for (int j = 0; j < 8; j++) {

				testTiles[n] = new TestTile(i, j, "grassland");
				n++;

			}
			;

		}
		return testTiles;
	}

	private void setupCanvasAndContext() {
		canvas.setWidth(WIDTH + "px");
		canvas.setCoordinateSpaceWidth(WIDTH);
		canvas.setHeight(HEIGHT + "px");
		canvas.setCoordinateSpaceHeight(HEIGHT);

		context = canvas.getContext2d();
		context.setStrokeStyle("Black");
	}

	private void moveUnitTo(Tile t) {

		if ((Math.abs((tileWithUnit.getX() - t.getX())) <= 1)
				&& (Math.abs((tileWithUnit.getY() - t.getY())) <= 1)) {

			String position = String.valueOf(t.getX()) + ","
					+ String.valueOf(t.getY());

			tileWithUnit.getThingList().remove(0);

			t.getThingList().add(new TestUnit());
			tileWithUnit = t;
			bd.drawBoard();
			msgsLabel.setText("Unit Moved to " + position);
		}
		else
		{
			msgsLabel.setText("Unit can only move to adjacent positions");
		}

	}

	// Event Handler nested classes

	private final class CanvasClickHandler implements ClickHandler {
		public void onClick(ClickEvent event) {
			Tile t = bd
					.getTileFromScreenCoordinates(event.getX(), event.getY());

			String position = "Out of Board";

			if (t != null) {
				position = String.valueOf(t.getX()) + ","
						+ String.valueOf(t.getY());
			}

			if (displayPositionOption.getValue()) {

				msgsLabel.setText(" User Clicked on Tile : " + position);

			} else {

				if (t != null) {

					moveUnitTo(t);

				}
			}

		}
	}

	private final class ZoomOutButtonClickHandler implements ClickHandler {
		public void onClick(ClickEvent event) {

			bd.setZoom(bd.getZoom() - 10);

			context.clearRect(0, 0, WIDTH, HEIGHT);
			bd.drawBoard();
			msgsLabel.setText("Zoom : " + String.valueOf(bd.getZoom()));

		}
	}

	private final class ZoomInButonClickHandler implements ClickHandler {
		public void onClick(ClickEvent event) {

			bd.setZoom(bd.getZoom() + 10);

			context.clearRect(0, 0, WIDTH, HEIGHT);
			bd.drawBoard();
			msgsLabel.setText("Zoom : " + String.valueOf(bd.getZoom()));

		}
	}

	private final class DrawBoardClickHandler implements ClickHandler {
		public void onClick(ClickEvent event) {

			bd.drawBoard();
			msgsLabel.setText("Board Drawn");
		}
	}
}
